#include "./../inc/game_manager.h"

GameManager *GameManager::m_instance = NULL;

std::mutex mtx; // 互斥锁

GameManager::~GameManager()
{
    // 释放单实例
    if (snake)
    {
        Snake::delInstance();
        snake = nullptr;
    }
    if (game_map)
    {
        GameMap::delInstance();
        game_map = nullptr;
    }
    if (touch)
    {
        Touch::delInstance();
        touch = nullptr;
    }
    if (lcd)
    {
        Lcd::delInstance();
        lcd = nullptr;
    }
}

GameManager *GameManager::instance()
{
    // 如果没有实例则创建实例
    if (m_instance == NULL)
    {
        m_instance = new GameManager();
    }
    return m_instance;
}

void GameManager::delInstance()
{
    // 释放实例空间
    delete m_instance;
    m_instance = NULL;
}

void GameManager::init()
{
    // 初始化触摸屏--》单实例
    touch = Touch::instance();
    // 初始化液晶屏--》单实例
    lcd = Lcd::instance();
    // 初始化游戏地图--》单实例
    game_map = GameMap::instance(lcd->addr());
    // 初始化贪吃蛇--》单实例
    snake = Snake::instance(lcd->addr());
    // 获取ShowFont--》单实例
    showFont = ShowFont::instance();
    // 获取页面管理器--》单实例
    pageManager = PageManager::instance();
    // 初始化游戏页面
    gamePage = GamePage::instance(snake, lcd, showFont, this);
    // 初始化菜单弹窗
    menuPopup = MenuPopup::instance(this, lcd);
    // 初始化选择难度弹窗
    levelPopup = LevelPopup::instance(this, lcd);
    // 初始化主页面
    mainPage = MainPage::instance(this, lcd);
    // 初始化音乐
    music = Music::instance();

    // 添加页面
    pageManager->addPage(gamePage);
    pageManager->addPage(menuPopup);
    pageManager->addPage(levelPopup);
    pageManager->addPage(mainPage);

    pageManager->switchPage(mainPage);
}

// 游戏开始
void GameManager::start()
{
    std::thread touch_thread(&GameManager::touchThreadWrapper, m_instance);
    std::thread game_thread(&GameManager::gameThreadWrapper, m_instance);
    std::thread music_thread(&GameManager::musicThreadWrapper, m_instance);

    touch_thread.join();
    game_thread.join();
    music_thread.join();
}

void GameManager::touchThreadWrapper(GameManager *manager)
{
    manager->touchTask();
}

void GameManager::gameThreadWrapper(GameManager *manager)
{
    manager->gameTask();
}

void GameManager::musicThreadWrapper(GameManager *manager)
{
    manager->musicTask();
}

void GameManager::touchTask()
{
    Point p = {0, 0};
    while (true)
    {
        touch->wait(p);
        pageManager->handleTouchEvent(p); // 由页面管理器分发触摸事件
    }
}

void GameManager::gameTask()
{
    bool over_flag = false;
    while (true)
    {
        while (is_game_over == false)
        {
            over_flag = false;
            if (!is_running)
            {
                usleep(100000);
                continue;
            }
            usleep(1000000 * speed / 10);
            snake->move(game_map, score, speed, is_game_over, max_speed, min_speed, is_create_ai_snake);
            if (ai_snake != nullptr)
            {
                bool flag = ai_snake->move();
                if (!flag) // 如果AI贪吃蛇死亡，则销毁
                {
                    destroy_ai_snake();
                    ai_snake = nullptr;
                }
            }
            // 判断是否需要创建AI贪吃蛇
            if (is_create_ai_snake)
            {
                if (ai_snake != nullptr)
                {
                    destroy_ai_snake(); // 如果已经存在AI贪吃蛇，则销毁
                    ai_snake = nullptr;
                }
                else
                {
                    create_ai_snake();
                }
                is_create_ai_snake = false;
            }

            game_map->generateRandomFood();

            gamePage->showInfo(); // 更新游戏信息
        }

        if (over_flag == false && pageManager->getCurrentPage() == gamePage)
        {
            pageManager->switchPage(menuPopup);
            gamePage->showGameOver(); // 游戏结束
            over_flag = true;
        }
    }
}

void GameManager::musicTask()
{
    BasePage *lastPage = nullptr; // 记录上一次的页面
    while (true)
    {
        BasePage *currentPage = pageManager->getCurrentPage();

        if (lastPage != currentPage)
        {
            if (pageManager->getCurrentPage() == gamePage)
            {
                music->playGameMusic();
            }
            else if (pageManager->getCurrentPage() == mainPage)
            {
                music->playMainMusic();
            }
            else
            {
                music->stopMusic();
            }
            lastPage = currentPage;
        }
        sleep(1);
    }
}

void GameManager::gameInit(int _level)
{
    // 初始化
    score = 0;
    is_create_ai_snake = false;
    is_game_over = false;
    is_running = true;
    level = _level;

    // 销毁当前地图单例
    GameMap::delInstance();
    game_map = GameMap::instance(lcd->addr(), level);

    max_speed = game_map->getMaxSpeed();
    min_speed = game_map->getMinSpeed();
    speed = game_map->getInitSpeed();

    pageManager->switchPage(gamePage);

    // 初始化游戏
    game_map->init();
    snake->init();

    // 如果已经存在AI贪吃蛇，则先销毁
    if (ai_snake != nullptr)
    {
        destroy_ai_snake();
        ai_snake = nullptr;
    }

    // 判断是否需要创建AI贪吃蛇
    if (game_map->isCreatedAISnake())
    {
        // 初始化AI贪吃蛇--》单实例
        create_ai_snake();
    }
}

void GameManager::create_ai_snake()
{

    ai_snake = AISnake::instance(lcd->addr(), snake, game_map);
}

void GameManager::destroy_ai_snake()
{
    AISnake::delInstance();
    ai_snake = nullptr;
}

void GameManager::showMenuPopup()
{
    music->stopMusic();
    stopGame();
    sleep(1);
    pageManager->switchPage(menuPopup);
}

void GameManager::showLevelPopup()
{
    music->stopMusic();
    prevPage = pageManager->getCurrentPage();
    pageManager->switchPage(levelPopup);
}

void GameManager::showMainPage()
{
    music->stopMusic();
    pageManager->switchPage(mainPage);
}

void GameManager::stopGame()
{
    is_running = false;
}

void GameManager::reloadGame()
{
    music->stopMusic();
    is_running = true;
    gamePage->show();
    game_map->drawMap();
    snake->show();
    if (ai_snake != nullptr)
    {
        ai_snake->show();
    }
    pageManager->switchPage(gamePage);
}

void GameManager::backPage()
{
    music->stopMusic();
    pageManager->switchPage(prevPage);
}

void GameManager::mainReloadGame()
{
    music->stopMusic();
    if (is_game_over == true)
    {
        showLevelPopup();
        return;
    }
    reloadGame();
}